package ar.uba.is2.ec.matem.modelo.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;

import org.apache.log4j.Logger;

import ar.uba.is2.common.mensaje.contenido.Dato;
import ar.uba.is2.common.mensaje.contenido.Identificador;
import ar.uba.is2.ec.matem.dao.MedicionDao;
import ar.uba.is2.ec.matem.dao.ResultadoDeModeloDao;
import ar.uba.is2.ec.matem.dao.impl.MedicionDaoImpl;
import ar.uba.is2.ec.matem.dao.impl.ResultadoDeModeloDaoImpl;
import ar.uba.is2.ec.matem.datos.Medicion;
import ar.uba.is2.ec.matem.datos.ResultadoDeModelo;
import ar.uba.is2.ec.matem.motor.Regla;

public class DatosFetcher {
	
	private static final Logger logger = Logger.getLogger(DatosFetcher.class);

	public static DatosFetcher instance = new DatosFetcher();
	
	private static final int DIFERENCIA_MAXIMA_DE_TIEMPO_DE_MEDICION = 2000000000;
	
	private MedicionDao medicionDao = new MedicionDaoImpl();
	private ResultadoDeModeloDao resultadoDao = new ResultadoDeModeloDaoImpl();
	
	public Collection<Dato> fetchDatos(Collection<Regla> reglas) {
		
		Collection<Dato> datos = new ArrayList<Dato>();
		for (Regla regla : reglas) {
			Collection<Identificador> datosRequeridos = regla.getDatosRequeridos();
			
			for (Identificador identificador : datosRequeridos) {
				Dato dato = fetchDato(identificador);
				
				if (dato != null) {
					datos.add(dato);
				}
			}
		}
		
		return datos;
	}

	public Dato fetchDato(Identificador identificador) {
		Dato dato;
		switch (identificador.getTipoDato()) {
		case MEDICION:
			dato = obtenerMedicion(identificador);
			break;
		case RESULTADO:
			dato = obtenerResultado(identificador);
			break;
		default:
			dato = null;
			break;
		}
		return dato;
	}

	private Dato obtenerMedicion(Identificador identificador) {
		Medicion medicion = medicionDao.obtenerMedicion(identificador);
		return obtenerDato(identificador, medicion);
	}

	private Dato obtenerDato(Identificador identificador, Dato dato) {

		if (logger.isDebugEnabled()) {
			logger.debug(String.format("Se encontro el dato %s para el identificador %s", dato, identificador));
		}

		
		if (dato != null) {
			Date fechaMedicion = dato.getFecha();
			if (!checkTime(fechaMedicion)) {
				if (logger.isDebugEnabled()) {
					logger.debug(String.format("Se descarta el dato %s por fecha vieja", dato));
				}
				
				dato = null;
			}
		}

		return dato;
	}

	private boolean checkTime(Date fechaDato) {
		
		long time = fechaDato.getTime();
		
		long now = System.currentTimeMillis();
		
		return now - time < DIFERENCIA_MAXIMA_DE_TIEMPO_DE_MEDICION;
	}

	private Dato obtenerResultado(Identificador identificador) {

		ResultadoDeModelo resultado = resultadoDao.obtenerResultado(identificador);
		
		return obtenerDato(identificador, resultado);
	}

}
